#pragma once

#include <map>
#include <string>
#include "Sample.h"

/*
This enum describes the shape of a wave.
*/
enum WaveForm
{
	Sine = 0,
	Triangular,
	Square,
	Sawtooth,
	Random,
	UserFunc1,
	UserFunc2,
	UserFunc3,
	Freq2,
	Freq3,
	Freq4,
	Freq5,
	Freq6,
	Freq7,
	Freq8,
	Freq9
};

/*
Utility storage for looping through a sample
*/
struct WaveComponent
{
	int waveIndex;
	int phaseIndex;
	WaveForm waveForm;
	double frequencyStart;
	double intensity;
	Sample sample;
};


typedef std::map<std::string, Sample*> StringSoundMap;
typedef std::map<WaveForm, std::string> WaveFormMap;
typedef void(*SampleCallback)(Sample*,unsigned int,unsigned int);

/*
Class for creating sounds of any frequency.
Once a sound has been created it is cached and is from there on very cheap to retrieve.
*/
class SoundBank
{
public:
	SoundBank(unsigned int samplingRate);
	~SoundBank(void);

	/*
	Returns a sample of the specified frequency, with the specified wave form shape.
	*/
	Sample* GetSample(WaveForm waveForm, unsigned int frequency);

	SampleCallback userFunc1Cb;
	SampleCallback userFunc2Cb;
	SampleCallback userFunc3Cb;
private:
	int samplingRate;
	StringSoundMap soundMap;
	WaveFormMap waveFormNames;

	/*
	Helper methods for creating sound samples
	*/
	void SampleName(WaveForm waveForm, unsigned int frequency, double intensity, std::string& destination);
	Sample* GetSample(WaveForm waveForm, unsigned int frequency, double intensity);
	Sample* GetSample(std::string& name);
	Sample* GetSample(WaveForm waveForm, unsigned int frequency, void(*SampleCb)(Sample*,unsigned int,unsigned int));
	Sample* GetSample(WaveForm waveForm, unsigned int frequency, double intensity, void(*SampleCb)(Sample*,unsigned int,unsigned int));
	void SampleLoop(Sample* sample, unsigned int phaseCount, void(*SampleLoopCb)(Sample*,unsigned int,unsigned int,unsigned int));
	Sample* CreateAndAddSample(std::string& name, unsigned int frequency, void(*SampleCb)(Sample*,unsigned int,unsigned int));
	Sample* TriangularSample(std::string& name, unsigned int frequency);
	Sample* SineSample(std::string& name, unsigned int frequency);
	Sample* RandomSample(std::string& name, unsigned int frequency);
	Sample* SquareSample(std::string& name, unsigned int frequency);
	Sample* SawtoothSample(std::string& name, unsigned int frequency);
	Sample* UserFunc1Sample(std::string& name, unsigned int frequency);
	Sample* UserFunc2Sample(std::string& name, unsigned int frequency);
	Sample* UserFunc3Sample(std::string& name, unsigned int frequency);
	void AddSample(std::string& name, Sample* sound);
};
